import { Controller } from 'egg';
import {join,resolve} from "path";
import {existsSync,mkdirSync,statSync,unlinkSync} from "fs";
import {Op} from 'sequelize'
import {createReadStream,createWriteStream} from "mz/fs"
import {pump} from "mz-modules"
//资源管理接口
export default class  ResourceController extends Controller {
    //可批量上传图片，视频等资源文件
    /**
     * @api {post} /manage/resource_uploads 批量上传资源
     * @apiName manageResourceUploads
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 批量上传资源
     * @apiParam {Number} product_id  产品ID
     * @apiParam {File[]} file  批量文件
     * @apiParam {String[]} contents  描述文本
     * @apiParam {Number} type 上传类型 1 产品 2 解决方案 3 服务支持 默认1 
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息
     * 
     */
    /**
     * 批量上传接口
     * 支持多文件上传，获取多个文件，遍历文件列表，构建基本信息如文件名称等，
     * 存入指定位置，返回路径并存入路径数组，返回结果
     */
    async uploads(){
        const { ctx ,app} = this;
        const {body}=ctx.request;
        let baseDir=app.config.baseDir;
        let type=body.type;
        //accessUrl+='images/';
        const files = ctx.request.files;
        let urls:object[]=[];
        let index=0;
        try {
            for (const file of files) {
                let userDirPath=join(baseDir,'app/public/');
                if(!existsSync(userDirPath)) {mkdirSync(userDirPath)};
                let filename : string = Date.now() + '' + ctx.helper.parse_int(Math.random() * 10000)+file.filename.toLowerCase();
                let accessUrl : string =app.config.accessPath;
                let tmp=this.makeUrl(file,type);
                userDirPath=tmp.userDirPath;
                accessUrl=tmp.accessUrl;
                const targetPath = join(userDirPath, filename);
                
                const source = createReadStream(file.filepath);
                const target = createWriteStream(targetPath);
                await pump(source, target);

                urls.push({
                    resource_url:accessUrl+filename,
                    resource_name:file.filename ? file.filename.split(".").shift() : '',
                    resource_content:body.resource_content &&body.resource_content[index]? body.resource_content[index]:''
                });
            }
            ctx.body={
                message:'操作成功',
                code:200,
                data:{
                    resouces:urls
                }
            }
        }catch(error){
            console.log(error);
            ctx.body={
                message:'操作失败',
                code:0
            }
        } finally {
            await ctx.cleanupRequestFiles();
        }   
    }
    /**
     * 构建路径名称，
     * 根据字段type构建不同的文件夹，可以方便查看
     */
    makeUrl(file,type){
        const {app} = this;
        let baseDir=app.config.baseDir;
        let mime=file.mime;
        let userDirPath=join(baseDir,'app/public/');
        let accessUrl : string =app.config.accessPath;
        if(!existsSync(userDirPath)) {mkdirSync(userDirPath)};
        if(type=='1'){
            userDirPath=join(userDirPath,'product/');
            
            accessUrl+='product/';
        }else if(type=='2'){
            userDirPath=join(userDirPath,'solution/');
            accessUrl+='solution/';
        }else if(type=='3'){
            userDirPath=join(userDirPath,'service/');
            accessUrl+='service/';
        }else{
            userDirPath=join(userDirPath,'product/');
            accessUrl+='product/';
        }
        if(mime.indexOf("video")>-1){
            userDirPath=join(userDirPath,'videos/');
            accessUrl+='videos/';
        }
        if(mime.indexOf("image")>-1){
            userDirPath=join(userDirPath,'images/');
            accessUrl+='images/';
        }
        return {
            userDirPath,
            accessUrl
        }
    }
    //单个上传图片，视频等资源文件
    /**
     * @api {post} /manage/resource_upload 上传资源
     * @apiName manageResourceUpload
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 上传资源
     * @apiParam {Number} parent_id  产品ID或解决方案ID或服务ID
     * @apiParam {File} file  批量文件
     * @apiParam {String} resource_content  文本内容
     * @apiParam {String} resource_name  名称/标题
     * @apiParam {String} resource_abstract  简介
     * @apiParam {Number} type 上传类型 1 产品 2 解决方案 3 服务支持 默认1 
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息
     * 
     */
    /**
     * 上传接口
     * 支持单个文件，构建基本信息如文件名称等，
     * 存入指定位置，返回路径，返回结果
     */
    async upload(){
        const { ctx ,app} = this;
        let {body}=ctx.request;
        let type=body.type;
        let parent_id=body.parent_id;
        const file = ctx.request.files[0];
        try {
            if(!file){
                return ctx.body=ctx.helper.error_result("没有指定资源文件")
            }
            let filename : string = Date.now() + '' + ctx.helper.parse_int(Math.random() * 10000)+file.filename.toLowerCase();
            let tmp=this.makeUrl(file,type);
            let userDirPath=tmp.userDirPath;
            let accessUrl=tmp.accessUrl;
            const targetPath = join(userDirPath, filename);
            const source = createReadStream(file.filepath);
            const target = createWriteStream(targetPath);
            await pump(source, target);
            let result=await app.model.Resource.create({
                type,
                parent_id:parent_id,
                resource_url:accessUrl+filename,
                resource_name:body.resource_name,
                resource_abstract:body.resource_abstract,
                resource_content:body.resource_content
            })
            if(result&&result['resource_id']){
                return ctx.body={
                    message:'操作成功',
                    code:200,
                    data:{
                        resource:result
                    }
                }
            }  
        } catch(error){
            
        }finally{
          await ctx.cleanupRequestFiles();
        }
        ctx.body={
            message:'上传资源异常',
            code:0
        }
    }
    
    //修改资源
    /**
     * @api {post} /manage/resource_update 修改资源
     * @apiName manageResourceUpdate
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 上传资源
     * @apiParam {Number} parent_id  产品ID
     * @apiParam {Number} resource_id  资源ID
     * @apiParam {File} file  批量文件
     * @apiParam {String} resource_content  文本内容
     * @apiParam {String} resource_name  名称/标题
     * @apiParam {String} resource_abstract  简介
     * @apiParam {Number} type 上传类型 1 产品 2 解决方案 3 服务支持 默认为资源本身类型
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息
     * 
     */
    /**
     * 过程：
     * 查询指定资源，获取资源路径，删除原来路径对应的文件，修改资源路径为新的路径
     */
    async update(){
        const { ctx ,app} = this;
        let {body}=ctx.request;
        let type=body.type;
        let parent_id=body.parent_id;
        let file:any='';
        if(ctx.request.files){
            file= ctx.request.files[0];
        }

        if(!body.resource_id){
            return ctx.body={
                message:'没有指定资源ID',
                code:0
            }
        }
        let resource=await app.model.Resource.findByPk(body.resource_id)
        let origin_url=resource ? resource['resource_url'] : '';
        if(origin_url.indexOf("public")>-1){
            origin_url=origin_url.split('/public/')[1];
        }
        let origin_file_url=join(app.baseDir,'app/public',origin_url);
        try {
            let accessUrl='';
            if(file){
                let filename : string = Date.now() + '' + ctx.helper.parse_int(Math.random() * 10000)+file.filename.toLowerCase();
                let tmp=this.makeUrl(file,type);
                let userDirPath=tmp.userDirPath;
                accessUrl=tmp.accessUrl+filename;
                const targetPath = join(userDirPath, filename);
                const source = createReadStream(file.filepath);
                const target = createWriteStream(targetPath);
                await pump(source, target);
            }
            if(!resource||!resource['resource_id']){
                return ctx.body={
                    message:'没有找到指定的资源，无法修改',
                    code:200
                }
            }
            let tmp_obj={};
            if(accessUrl){
                tmp_obj['resource_url']=accessUrl;
            }
            if(parent_id){
                tmp_obj['parent_id']=parent_id
            }
            if(type){
                tmp_obj['type']=type
            }

            tmp_obj=ctx.helper.assign_basic(tmp_obj,body);
            
            let result=await app.model.Resource.update({
                ...tmp_obj
            },{
                where:{
                    resource_id:body.resource_id
                }
            })
            if(existsSync(origin_file_url)&&statSync(origin_file_url).isFile()){
                unlinkSync(origin_file_url);
            }
            if(result[0]==1){
                return ctx.body={
                    message:'操作成功',
                    code:200
                }
            }else{
                return ctx.body={
                    message:'未修改数据',
                    code:200
                }
            }
        } catch(error){
            ctx.body={
                message:'修改资源异常',
                code:0
            }
        }finally{
          await ctx.cleanupRequestFiles();
        }
        
    }
    //删除资源
    /**
     * @api {post} /manage/resource_del 资源删除
     * @apiName manageResourceDel
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 资源删除
     * @apiParam {Number} resource_id  资源ID
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息
     * 
     */
    /**
     * 删除资源：
     * 获取资源访问路径，解析得到资源目录路径，删除指定资源，删除资源表中记录
     */
    async del(){
        const { ctx ,app} = this;
        let {body}=ctx.request;
        if(!body.resource_id){
            return ctx.body={
                message:'没有指定资源ID',
                code:0
            }
        }
        try {
            let resource=await app.model.Resource.findByPk(body.resource_id)
            let origin_url=resource ? resource['resource_url'] : '';

            if(origin_url.indexOf("public")>-1){
                origin_url=origin_url.split('/public/')[1];
            }
            let origin_file_url=join(app.baseDir,'app/public',origin_url);

            let result=await app.model.Resource.destroy({where:{resource_id:body.resource_id}});
            if(result){
                if(existsSync(origin_file_url)&&statSync(origin_file_url).isFile()){
                    unlinkSync(origin_file_url);
                }
                return ctx.body={
                    message:'操作成功',
                    code:200
                }
            }
        } catch (error) {
            
        }
        return ctx.body={
            message:'操作失败',
            code:0
        }
    }
    //资源列表
    /**
     * @api {get} /manage/resource_list 资源列表
     * @apiName manageResourceList
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 资源删除
     * @apiParam {Number} parent_id  父类ID（产品，服务，解决方案）
     * @apiParam {String} keyword  关键字查询
     * @apiParam {Number} type  关键字查询
     * @apiParam {Number} page  页面位置
     * @apiParam {Number} page_size  页面尺寸
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息 
     * @apiSuccess {Object} data 返回结果 
     * @apiSuccess {Object[]} data.data_info 资源列表 
     * @apiSuccess {Number} data.data_info.resource_id 资源ID 
     * @apiSuccess {String} data.data_info.resource_url 资源路径
     * @apiSuccess {String} data.data_info.resource_content 资源文本说明
     * @apiSuccess {String} data.data_info.resource_name 资源名称
     * @apiSuccess {String} data.data_info.parent_id 父类ID
     * @apiSuccess {String} data.data_info.parent_name 父类名称
     * @apiSuccess {String} data.data_info.type 1产品2解决方案3服务
     * @apiSuccess {Number} data.data_count 数据总数
     * @apiSuccess {String} data.page_count 页面总数
     * 
     */
    /**
     * 分页查询所有资源
     * 参数：
     *  condition 检索条件
     * 输出：
       {Number} code 返回状态码 0失败  200成功
     * {String} message 返回状态对应提示消息 
     * {Object} data 返回结果 
     * {Object[]} data.data_info 资源列表 
     * {Number} data.data_info.resource_id 资源ID 
     * {String} data.data_info.resource_url 资源路径
     * {String} data.data_info.resource_content 资源文本说明
     * {String} data.data_info.resource_name 资源名称
     * {String} data.data_info.parent_id 父类ID
     * {String} data.data_info.parent_name 父类名称
     * {String} data.data_info.type 1产品2解决方案3服务
     * 过程：
     *  构建分页查询条件
     *  分页查询数据，分页结果处理逻辑，返回结果
     */
    async list(){
        let {ctx}=this;
        const {query}=ctx.request;
        try {
            let condition:any={}
            if(query.keyword){
                let keyword=query.keyword;
                condition['resource_name']={[Op.like]: '%'+ keyword +'%'};
            }
            if(query.type){
                condition['type']=query.type;
            }
            if(query.parent_id){
                condition['parent_id']=query.parent_id;
            }
            
            let order_condition=[
                ['create_time', 'DESC']
            ];
            //ctx.helper.sort_order(order_condition);
            let resource_list=await ctx.service.resource.find_and_count_all(condition,order_condition,query);
            ctx.body=resource_list
        } catch (error) {
            ctx.body=ctx.helper.error_result("查询异常");
        }
    }
    //资源详情
    /**
     * @api {get} /manage/resource_info 资源详情
     * @apiName manageResourceInfo
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 资源详情
     * @apiParam {Number} resource_id  资源ID
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {Number} resource_id 资源ID 
     * @apiSuccess {Object} data 返回状态对应提示消息 
     * @apiSuccess {String} data.resource_img 返回状态对应提示消息 
     * @apiSuccess {String} data.resource_vedio 返回状态对应提示消息 
     * @apiSuccess {String} data.resource_content 返回状态对应提示消息 
     * @apiSuccess {String} data.resource_name 返回状态对应提示消息 
     */
    async info(){
        let {ctx}=this;
        const {query}=ctx.request;
        try {
            if(!query.resource_id){
                return ctx.body={
                    message:'操作成功',
                    code:200
                }
            }
            let resource_info=await ctx.service.common.find_one(query,"Resource",'resource_id');
            resource_info=await ctx.service.resource.get_parent(resource_info);
            ctx.body=ctx.helper.success_result("操作成功",resource_info);
        } catch (error) {
            ctx.body=ctx.helper.error_result("查询异常");
        }
    }

     /**
     * @api {post} /manage/upload_url 上传资源仅返回上传路径
     * @apiName manageResourceUploadUrl
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 上传资源仅返回上传路径
     * @apiParam {Number} type  type 上传类型 1 产品 2 解决方案 3 服务支持 4 关于我们 5 banner
     * @apiParam {File} file  单个文件
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息
     * 
     */
    /**
     * 名称：上传资源返回访问路径
     * 过程：
     *   上传文件，根据字段type判断上传资源类型，方便指定不同存放目录
     *   保存文件到指定目录，返回资源访问目录
     */
    async upload_url(){
        const {ctx} = this;
        const {body} = ctx.request;

        const file = ctx.request.files[0];
        
        let type=body.type;
        try {
            let floder_path="";
            switch (type) {
                case '1':
                    floder_path="product/"
                    break;
                case '2':
                    floder_path="solution/"
                    break;
                case '3':
                    floder_path="service/"
                    break;
                case '4':
                    floder_path="about/"
                    break;
                case '5':
                    floder_path="banner/"
                    break;
                case '6':
                    floder_path='cover/'
                    break;
                default:
                    floder_path="product/"
                    break;
            }
            if(['1','2','3'].includes(type)){
                let mime=file.mime;
                if(mime.indexOf("video")>-1){
                    floder_path=join(floder_path,'videos/');
                }
                if(mime.indexOf("image")>-1){
                    floder_path=join(floder_path,'images/');
                }
            }
            console.log(floder_path)
            let resource_url=await ctx.service.common.to_target_path(file,floder_path);
            console.log(resource_url)
            if(resource_url){
                
                return ctx.body=ctx.helper.success_result("上传成功",{url:resource_url});
            }  
        } catch(error){
            console.log("error: ",error)
        }finally{
          await ctx.cleanupRequestFiles();
        }
        ctx.body=ctx.helper.error_result("上传失败")
    } 
    /**
     * @api {post} /manage/upload_urls 批量上传资源(仅返回上传路径)
     * @apiName manageResourceUploadUrls
     * @apiGroup Resource
     * @apiVersion 1.0.0
     * @apiDescription 批量上传资源(仅返回上传路径)
     * @apiParam {Number} type  type 上传类型 1 产品 2 解决方案 3 服务支持 4 关于我们 5 banner图
     * @apiParam {File} file  批量文件
     * @apiSuccess {Number} code 返回状态码 0失败  200成功
     * @apiSuccess {String} message 返回状态对应提示消息
     * 
     */
    /**
     * 名称：批量上传资源返回访问路径
     * 过程：
     *   批量上传的文件，遍历文件列表，根据字段type判断上传资源类型，方便指定不同存放目录
     *   保存文件到指定目录，将资源访问路径存入数组，遍历完成返回数组
     */
    async upload_urls(){
        const {ctx} = this;
        const {body} = ctx.request;
        const files = ctx.request.files;
        let type=body.type;
        console.log(files);
        console.log(body);
        try {
            let file_urls:string[]=[];
            for (const file of files) {
                let floder_path="";
                switch (type) {
                    case '1':
                        floder_path="product/"
                        break;
                    case '2':
                        floder_path="solution/"
                        break;
                    case '3':
                        floder_path="service/"
                        break;
                    case '4':
                        floder_path="about/"
                        break;
                    case '5':
                        floder_path="banner/"
                        break;
                    case '6':
                        floder_path='cover/'
                        break;
                    default:
                        floder_path="product/"
                        break;
                }
                if(['1','2','3'].includes(type)){
                    let mime=file.mime;
                    if(mime.indexOf("video")>-1){
                        floder_path=join(floder_path,'videos/');
                    }
                    if(mime.indexOf("image")>-1){
                        floder_path=join(floder_path,'images/');
                    }
                }
                let resource_url=await ctx.service.common.to_target_path(file,floder_path);
                if(resource_url){
                    file_urls.push(resource_url)
                } 
            }
            return ctx.body=ctx.helper.success_result("上传成功",{urls:file_urls});
        }  catch(error){
            
        }finally{
          await ctx.cleanupRequestFiles();
        }
        ctx.body=ctx.helper.error_result("上传失败")
    }
    /**
     * 下载资源
     */
    async download() {
        const {ctx} =this;
        const {url}=ctx.request;
        try {
            let fileName=url.split("download")[1];
            let basePath=process.cwd();
            const filePath = resolve(join(basePath,"/app/public",fileName));
            // ctx.attachment([filename], [options]) 将 Content-Disposition 设置为 “附件” 以指示客户端提示下载。
            ctx.attachment(filePath);
            const fileSize = statSync(filePath).size+"";
            let name=fileName.split("/").pop();
            ctx.set('Content-Length',fileSize) 
            ctx.set('Content-Disposition',`attachment; filename=${name}`)
            ctx.body = createReadStream(filePath);
        } catch (error) {
            ctx.body=ctx.helper.error_result("没有找到相关资源");
        }
        
    }
}

